# -*- coding: utf-8 -*-
import util

class Layer(object):
    """Base layer class. Keeps a map of properties.
    """

    def __init__(self, name):
        """Creates an empty layer.
	"""
        self.name = name
        self.visible = True
        self.properties = {}


class RectGridLayer(Layer):
    """A Layer made of a grid of rectangular cells.
    """

    def __init__(self, name, num_x_cells, num_y_cells, cell_size):
        """Creates a RectGridLayer.

        num_x_cells: number of horizontal cells.

        num_y_cells: number of vertical cells.

        cell_size: An integer for square cells and a 2-uple for
        rectangular cells.
    	"""
        super(RectGridLayer, self).__init__(name)
        self.cell_width, self.cell_height = util.unpack_or_dup(cell_size)
        self.num_x_cells = num_x_cells
        self.num_y_cells = num_y_cells

    def get_cells(self, region=None):
        """Generates cell position and data for a given region on a
        tuple ((x,y), data).

        The region is a rectangle specified by a 4-uple (x, y, w,
        h). (x, y) is the pos of the upper left corner of the
        rectangle.
        """
        if region:
            x, y, w, h = region
        else:
            x, y, w, h = 0, 0, self.width, self.height

        min_x = util.multiple(x, self.cell_width)
        min_y = util.multiple(y, self.cell_height)
        max_x = util.multiple(x + w, self.cell_width, floor=False)
        max_y = util.multiple(y + h, self.cell_height, floor=False)

        return (((x, y), self.get_data((x,y)))
                for x in xrange(min_x, max_x, self.cell_width)
                for y in xrange(min_y, max_y, self.cell_height))

    def get_data(self, pos):
        """Returns the data at a given position.

        Subclasses should override this method to provide useful data.
        """
        return None

    @property
    def size(self):
        return (self.width, self.height)

    @property
    def width(self):
        return self.num_x_cells * self.cell_width

    @property
    def height(self):
        return self.num_y_cells * self.cell_height

    def from_pixel(self, pixel_pos):
        """Converts a pixel position to a grid cell position.
        """
        return (int(pixel_pos[0])/self.cell_width,
                int(pixel_pos[1])/self.cell_height)

    def to_pixel(self, grid_pos):
        """Converts from grid to pixel coordinates
        """
        return (grid_pos[0]*self.cell_width,
                grid_pos*self.cell_height)


class TileLayer(RectGridLayer):
    """A layer composed por several tile indexes.

    This layer has an associated tileset and keeps a matrix of data.
    The matrix have a size self.width X self.height and keeps the tile
    index for each given position. The value -1 is a special index and
    it means that no tile is present on that cell.
    """

    def __init__(self, name, width, height, tileset):
        """
	"""
        super(TileLayer, self).__init__(name, width, height, tileset.tile_size)
        self.tileset = tileset
        self._data = [[-1] * self.width for i in range(self.num_y_cells)]

    def get_data(self, pos):
        """Returns tile data for the given position.
        """
        x, y = self.from_pixel(pos)
        index = self._data[x][y]
        if index == -1:
            return None
        else:
            return self.tileset[index]

    def set_data(self, pos, data):
        """
        """
        x, y = self.from_pixel(pos)
        self._data[x][y] = data

    def draw(self, event, gc):
        """Draw the layer on the given window.
        """
        a = event.area
        region = a.x, a.y, a.width, a.height
        window = event.window

        for ((x,y), pixbuf) in self.get_cells(region):
            if pixbuf:
                window.draw_pixbuf(gc, pixbuf, 0,0, x,y)
